/* 
 * File:   arealight.cpp
 * Author: chaterolas
 * 
 * Created on 26 de junio de 2009, 02:49 PM
 */

#include "arealight.h"

#include "../base/matriz.h"

/**
 * Crea una nueva instancia de superficie luminosa a partir de los
 * siguientes parametros :
 * @param name
 * @param color
 * @param pos (posicion de referencia de la suoerficie luminosa)
 * @param dir (direccion en la que apunta la luz de esta superficie)
 * @param intensity (intencidad de la luz de la suerficie)
 * @param size (tamaño de la superficie)
 * @param samples (numero de muestra a considerar en el algoritmo de Monte Carlo)
 */
AreaLight::AreaLight(double cR, double cG, double cB,
        double px, double py, double pz, double dx, double dy, double dz,
        double intensity, double size, int samples) :
Light(cR, cG, cB, px, py, pz, dx, dy, dz, intensity, samples) {


    dir->normalize();

    double ms = (double) size / 2.0;

    Vector3D *ulb = new Vector3D(ms, ms, 0);
    Vector3D *urb = new Vector3D(-1.0*ms, ms, 0);
    Vector3D *blb = new Vector3D(ms, -1.0*ms, 0);
    Vector3D *brb = new Vector3D(-1.0*ms, -1.0*ms, 0);

    Vector3D *cw = new Vector3D(*dir);
    Vector3D *up = new Vector3D(0,1,0);
    Vector3D *cu = up->cross(*cw);   cu->normalize();

    Vector3D *temp = *cw * (-1.0);
    
    Vector3D *cv = cu->cross(*temp);

    Matriz *tm = new Matriz(*cu, *cv, *cw);
    tm->transpose();

    Vector3D *ulb1 = *tm * (*ulb);
    Vector3D *urb1 = *tm * (*urb);
    Vector3D *blb1 = *tm * (*blb);
    Vector3D *brb1 = *tm * (*brb);


    delete ulb;
    delete urb;
    delete blb;
    delete brb;
    delete temp;
    delete cw;
    delete up;
    delete cu;
    delete cv;
    delete tm;

    *ulb1 += *pos;
    *urb1 += *pos;
    *blb1 += *pos;
    *brb1 += *pos;

    hd = *urb1  - *ulb1;
    vd = *blb1 - *ulb1;

    corner = brb1;

    delete urb1;
    delete ulb1;
    delete blb1;
}

/**
 * Destruye una instancia de superficie luminosa junto con sus atributos
 * pertinentes.
 */
AreaLight::~AreaLight() {
    delete hd;
    delete vd;
    delete corner;
}

/**
 * Regresa el tipo asociado a este primitivo
 * @return SURFACE
 */
int AreaLight::getType() {
    return SURFACE;
}

/**
 * Regresa el vector que representa la esquina superior izquierda de la caja que
 * representa la funte  luminosa
 * @return corner
 */
Vector3D *AreaLight::getCorner() {
    return corner;
}

/**
 * Regresa la direccion del lado horizontal del plano de luz
 * @return hd
 */
Vector3D *AreaLight::getHSide() {
    return hd;
}

/**
 * Regresa la direccion del lado vertical del plano de luz
 * @return vd
 */
Vector3D *AreaLight::getVSide() {
    return vd;
}

